#ifndef _INPUT_SYSTEM_
#define _INPUT_SYSTEM_

#include "../LogicSystem.h"
#include "Keys.h"
#include <string>
#include <map>

//Forward declaration since we only need a pointer in here. Reduces dependencies
class InputBuffer;

/*
	Inherit and override these interfaces to receive input callbacks if you are the interface in focus.
	To set your interface in focus call:
	InputSystem::Instance().setFocus(this);
	from inside your class
*/
class InputInterface
{
public:
	virtual ~InputInterface() {}
	virtual void onMouseButtonDown(KEY_TYPE, int, int) = 0;
	virtual void onMouseButtonUp(KEY_TYPE , int, int) = 0;
	
	virtual void onKeyDown(KEY_TYPE) = 0;
	virtual void onKeyUp(KEY_TYPE) = 0;
	
	virtual void onMouseWheelUp() = 0;
	virtual void onMouseWheelDown() = 0;

	virtual void onMouseMove(int, int) = 0;
};

/*
	The global system that handles user input
*/
class InputSystem: public LogicSystem
{
	InputInterface* currentInterface;			//pointer to which interface currently has focus
	InputBuffer *userInput;					//a buffer for reading from stdin
	std::map<std::string, KEY_TYPE> keyNames;	//a map of strings to keys to use
	
	void checkstdIn();
	void buildKeyNameMap();
	
	//The void functions that are registered with the windowing system
	friend void callbackOnMousePosChange(int x, int y);
	friend void callbackOnMouseButtonChange(KEY_TYPE button, int action);
	friend void callbackOnKeyboardButtonChange(KEY_TYPE button, int action);
	friend void callbackOnMouseWheelChange(int pos);
	
	//Singleton so no one can make one of these except ourselves
	InputSystem();
	InputSystem(const InputSystem&);
	InputSystem& operator = (const InputSystem&) { return *this; };
	
public:
	static inline InputSystem& Instance() {	static InputSystem is; return is;	}
	
	void update(long currTime = 0);			//Updates the state of the system
	bool init(const CmdLineArgs& args);
	void kill();
	void terminate();
	
	void setFocus(InputInterface* i);			//Sets the focus of input to the passed in interface
	friend KEY_TYPE getKey(const std::string&);	//Way to access the keyNames map
};

#endif
